package com.example.megaandroidrssreader;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public final class RssReaderDaoImpl implements RssReaderDao {

	private RssReaderDbHelper mDbHelper;
	
	public RssReaderDaoImpl(Context context) {
		mDbHelper = RssReaderDbHelper.newInstance(context);
	}
	
	@Override
	public RssSource getRssSource(String url) {
		RssSource rssSource = null;
		if (url != null) {
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			Cursor cur = db.rawQuery("SELECT 1 FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME +
					" WHERE " + RssReaderDbHelper.RssSourcesEntry.CN_LINK + " = ?", new String[] { url });
			if (cur.moveToFirst()) {
				rssSource = new RssSource();
				rssSource.mTitle = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry.CN_TITLE));
				rssSource.mUrl = url;
				byte[] byteArrayIcon = cur.getBlob(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry.CN_ICON));
				rssSource.mFavicon = BitmapFactory.decodeByteArray(byteArrayIcon, 0, byteArrayIcon.length);
			}
			cur.close();
		}
		return rssSource;
	}

	@Override
	public ArrayList<RssSource> getRssSources() {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		Cursor cur = db.rawQuery("SELECT * FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME,  null);
		ArrayList<RssSource> rssSources = new ArrayList<RssSource>();
		while (cur.moveToNext()) {
			RssSource rssSource = new RssSource();
			rssSource.mTitle = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry.CN_TITLE));		
			rssSource.mUrl = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry.CN_LINK));		
			byte[] byteArrayIcon = cur.getBlob(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry.CN_ICON));
			if (byteArrayIcon != null) {
				rssSource.mFavicon = BitmapFactory.decodeByteArray(byteArrayIcon, 0, byteArrayIcon.length);
			}
			rssSources.add(rssSource);
		}
		cur.close();
		return rssSources;
	}

	@Override
	public boolean addRssSource(RssSource rssSource) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		if (! isSourceUrlAlreadyInTable(rssSource.mUrl)) {
			ContentValues values = new ContentValues();
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_LINK, rssSource.mUrl);
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_TITLE, rssSource.mTitle);
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_ICON, bitmapToByteArray(rssSource.mFavicon));
			db.insert(RssReaderDbHelper.RssSourcesEntry.TABLE_NAME, null, values);
			return true;
		}
		return false;
	}

	@Override
	public boolean addAllRssSources(ArrayList<RssSource> rssSources) {
		boolean result = false;
		for (RssSource rssSource: rssSources) {
			if (addRssSource(rssSource)) {
				result = true;
			}
		}
		return result;
	}
	
	@Override
	public boolean updateRssSource(RssSource oldRssSource, RssSource newRssSource) {
		if (isSourceUrlAlreadyInTable(oldRssSource.mUrl)) {
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_LINK, newRssSource.mUrl);
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_TITLE, newRssSource.mTitle);
			values.put(RssReaderDbHelper.RssSourcesEntry.CN_ICON, bitmapToByteArray(newRssSource.mFavicon));
			db.update(RssReaderDbHelper.RssSourcesEntry.TABLE_NAME,
					values,
					RssReaderDbHelper.RssSourcesEntry.CN_LINK + " = ?",
					new String[] {oldRssSource.mUrl});
			return true;
		}
		return false;
	}

	@Override
	public boolean deleteRssSource(RssSource rssSource) {
		if (isSourceUrlAlreadyInTable(rssSource.mUrl)) {
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			db.delete(RssReaderDbHelper.RssSourcesEntry.TABLE_NAME, RssReaderDbHelper.RssSourcesEntry.CN_LINK + "= ?",
					new String[]{rssSource.mUrl});
			return true;
		}
		return false;
	}

	@Override
	public void deleteAllRssSources() {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		db.delete(RssReaderDbHelper.RssSourcesEntry.TABLE_NAME, "", null);
	}
	
	private boolean isSourceUrlAlreadyInTable (String url) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		Cursor cur = db.rawQuery("SELECT 1 FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME +
				" WHERE " + RssReaderDbHelper.RssSourcesEntry.CN_LINK + " = ?", new String[]{ url });
		if (cur.getCount() > 0) {
			cur.close();
			return true;
		}
		cur.close();
		return false;
	}
	
	protected static byte[] bitmapToByteArray (Bitmap bitmap) {
		byte[] byteArray = null;
		if (bitmap != null) {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
			byteArray = bos.toByteArray();
		}
		return byteArray;
	}

	@Override
	public int getViewModeSetting() {
		int viewMode = 0;
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		Cursor cur = db.rawQuery("SELECT * FROM " + RssReaderDbHelper.SettingsEntry.TABLE_NAME +
				" WHERE " + RssReaderDbHelper.SettingsEntry.CN_PARAM + " = ?", new String[]{ AppSettings.VIEW_MODE });
		if (cur.moveToFirst()) {
			viewMode = cur.getInt(cur.getColumnIndex(RssReaderDbHelper.SettingsEntry.CN_VALUE));
		}
		cur.close();
		return viewMode;
	}

	@Override
	public void setViewModeSetting(int viewModeSetting) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put(RssReaderDbHelper.SettingsEntry.CN_PARAM, AppSettings.VIEW_MODE);
		values.put(RssReaderDbHelper.SettingsEntry.CN_VALUE, viewModeSetting);
		Cursor cur = db.rawQuery("SELECT 1 FROM " + RssReaderDbHelper.SettingsEntry.TABLE_NAME +
				" WHERE " + RssReaderDbHelper.SettingsEntry.CN_PARAM + " = ?", new String[]{ AppSettings.VIEW_MODE });
		if (cur.getCount() > 0) {
			db.update(RssReaderDbHelper.SettingsEntry.TABLE_NAME, values, RssReaderDbHelper.SettingsEntry.CN_PARAM + " = ?", new String[] { AppSettings.VIEW_MODE });
		} else {
			db.insert(RssReaderDbHelper.SettingsEntry.TABLE_NAME, null, values);
			
		}
		cur.close();
	}

	@Override
	public ArrayList<RssItem> getAllRssItems(RssSource rssSource) {
		return getRssItems(rssSource, Integer.MAX_VALUE);
	}

	@Override
	public ArrayList<RssItem> getRssItems(RssSource rssSource, int limit) {
		ArrayList<RssItem> rssItems = null;
		if (rssSource != null) {
			rssItems = new ArrayList<RssItem>();
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			String query = "SELECT * FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME +
					" INNER JOIN " + RssReaderDbHelper.RssItemsEntry.TABLE_NAME +
					" ON " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME + "." + RssReaderDbHelper.RssSourcesEntry._ID +
					" = " + RssReaderDbHelper.RssItemsEntry.TABLE_NAME + "." + RssReaderDbHelper.RssItemsEntry.CN_SOURCEID + 
					" WHERE " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME + "." + RssReaderDbHelper.RssSourcesEntry.CN_LINK + "= ? " +
					" ORDER BY " + RssReaderDbHelper.RssItemsEntry._ID + " DESC " +
					" LIMIT " + limit;
			Cursor cur = db.rawQuery(query, new String[] { rssSource.mUrl });
			while (cur.moveToNext()) {
				RssItem rssItem = new RssItem();
				rssItem.title = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_TITLE));
				rssItem.description = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION));
				rssItem.fullText = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT));
				rssItem.pubDate = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_PUBDATE));
				rssItem.link = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_LINK));
				rssItem.pdaLink = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_PDALINK));
				rssItem.descriptionUncut = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION_UNCUT));
				rssItem.fullTextUncut = cur.getString(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT_UNCUT));

				byte[] byteArrayIcon = cur.getBlob(cur.getColumnIndex(RssReaderDbHelper.RssItemsEntry.CN_IMAGE));
				if (byteArrayIcon != null) {
					rssItem.icon = BitmapFactory.decodeByteArray(byteArrayIcon, 0, byteArrayIcon.length);
				}
				rssItems.add(rssItem);
			}
			cur.close();
		}
		return rssItems;
	}

	@Override
	public boolean addRssItems(RssSource rssSource, ArrayList<RssItem> rssItems) {
		boolean result = false;
		for (RssItem rssItem: rssItems) {
			if (addRssItem(rssSource, rssItem)) {
				result = true;
			}
		}
		return result;
	}

	@Override
	public boolean addRssItem(RssSource rssSource, RssItem rssItem) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		if (! isItemUrlAlreadyInTable(rssSource.mUrl, rssItem.link)) {
			ContentValues values = new ContentValues();
			values.put(RssReaderDbHelper.RssItemsEntry.CN_SOURCEID, getRssSourceId(rssSource.mUrl));
			values.put(RssReaderDbHelper.RssItemsEntry.CN_TITLE, rssItem.title);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_LINK, rssItem.link);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION, rssItem.description);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT, rssItem.fullText);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_PUBDATE, rssItem.pubDate);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_PDALINK, rssItem.pdaLink);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION_UNCUT, rssItem.descriptionUncut);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT_UNCUT, rssItem.fullTextUncut);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_IMAGE, bitmapToByteArray(rssItem.icon));
			db.insert(RssReaderDbHelper.RssItemsEntry.TABLE_NAME, null, values);
			return true;
		}
		return false;
	}

	@Override
	public boolean updateRssItem(RssSource rssSource, RssItem oldRssItem, RssItem newRssItem) {
		if (isItemUrlAlreadyInTable(rssSource.mUrl, oldRssItem.link)) {
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			ContentValues values = new ContentValues();
			values.put(RssReaderDbHelper.RssItemsEntry.CN_SOURCEID, getRssSourceId(rssSource.mUrl));
			values.put(RssReaderDbHelper.RssItemsEntry.CN_TITLE, newRssItem.title);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_LINK, newRssItem.link);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION, newRssItem.description);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT, newRssItem.fullText);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_PUBDATE, newRssItem.pubDate);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_PDALINK, newRssItem.pdaLink);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_DESCRIPTION_UNCUT, newRssItem.descriptionUncut);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_FULLTEXT_UNCUT, newRssItem.fullTextUncut);
			values.put(RssReaderDbHelper.RssItemsEntry.CN_IMAGE, bitmapToByteArray(newRssItem.icon));
			db.update(RssReaderDbHelper.RssItemsEntry.TABLE_NAME,
					values,
					RssReaderDbHelper.RssItemsEntry.CN_SOURCEID + " = ?" + " AND " + RssReaderDbHelper.RssItemsEntry.CN_LINK + " = ?",
					new String[] { Integer.toString(getRssSourceId(rssSource.mUrl)), oldRssItem.link });
			return true;
		}
		return false;
	}

	@Override
	public boolean deleteRssItem(RssSource rssSource, RssItem rssItem) {
		if (isItemUrlAlreadyInTable(rssSource.mUrl, rssItem.link)) {
			SQLiteDatabase db = mDbHelper.getWritableDatabase();
			db.delete(RssReaderDbHelper.RssItemsEntry.TABLE_NAME,
					RssReaderDbHelper.RssItemsEntry.CN_SOURCEID + "= ? AND " + RssReaderDbHelper.RssItemsEntry.CN_LINK + " = ?",
					new String[]{ Integer.toString(getRssSourceId(rssSource.mUrl)), rssItem.link});
			return true;
		}
		return false;
	}

	@Override
	public void deleteAllRssItems(RssSource rssSource) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		db.delete(RssReaderDbHelper.RssItemsEntry.TABLE_NAME,
				RssReaderDbHelper.RssItemsEntry.CN_SOURCEID + "= ?",
				new String[] { Integer.toString(getRssSourceId(rssSource.mUrl)) });
	}
	
	private boolean isItemUrlAlreadyInTable (String urlSource, String urlItem) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		String query = "SELECT * FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME +
				" INNER JOIN " + RssReaderDbHelper.RssItemsEntry.TABLE_NAME + 
				" ON " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME + "." + RssReaderDbHelper.RssSourcesEntry._ID +
				" = " + RssReaderDbHelper.RssItemsEntry.TABLE_NAME + "." + RssReaderDbHelper.RssItemsEntry._ID + 
				" WHERE " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME + "." + RssReaderDbHelper.RssSourcesEntry.CN_LINK + " = ? " + 
				" AND " + RssReaderDbHelper.RssItemsEntry.TABLE_NAME + "." + RssReaderDbHelper.RssItemsEntry.CN_LINK + " = ? ";
		Cursor cur = db.rawQuery(query, new String[]{ urlSource, urlItem });
		if (cur.getCount() > 0) {
			cur.close();
			return true;
		}
		cur.close();
		return false;
	}
	
	private int getRssSourceId (String sourceUrl) {
		SQLiteDatabase db = mDbHelper.getWritableDatabase();
		int id = 0;
		String query = "SELECT " + RssReaderDbHelper.RssSourcesEntry._ID + " FROM " + RssReaderDbHelper.RssSourcesEntry.TABLE_NAME +
				" WHERE " + RssReaderDbHelper.RssSourcesEntry.CN_LINK + " = ?";
		Cursor cur = db.rawQuery(query, new String[] { sourceUrl });
		if (cur.moveToNext()) {
			id = cur.getInt(cur.getColumnIndex(RssReaderDbHelper.RssSourcesEntry._ID));
		}
		return id;
	}
	
}
